Prashanth.S 19MID0020

Bivariate Analysis

Importing the libraries

library(ggplot2)
Want to understand how all the pieces fit together? Read R for Data Science: https://r4ds.had.co.nz/
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(gridExtra)

Attaching package: ‘gridExtra’

The following object is masked from ‘package:dplyr’:

    combine
library(tidyr)
library(reshape2)

Attaching package: ‘reshape2’

The following object is masked from ‘package:tidyr’:

    smiths
library(RColorBrewer)
library(ggrepel)
library(ggthemes)
library(GGally)
Registered S3 method overwritten by 'GGally':
  method from   
  +.gg   ggplot2
library(plotly)

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout

Importing the data-sets

df = read.csv('pokemon.csv')
head(df)

PreProcessing

cat("Number of instances  : ",nrow(df))
Number of instances  :  800
cat("\nNumber of attributes : ",ncol(df))

Number of attributes :  12
str(df1)
'data.frame':   18 obs. of  2 variables:
 $ unique.df.Type.1.: chr  "Grass" "Fire" "Water" "Bug" ...
 $ HP               : num  60 65 80 60 78 70 70 79 59.5 65.5 ...
summary(df1)
 unique.df.Type.1.        HP       
 Length:18          Min.   :59.50  
 Class :character   1st Qu.:65.12  
 Mode  :character   Median :69.25  
                    Mean   :68.67  
                    3rd Qu.:70.00  
                    Max.   :80.00  
for ( col in 1:ncol(df)) { 
  cat(colnames(df)[col])
  cat(" --> ")
  print(sum(is.na(df[,col])))
}
Name --> [1] 0
Type.1 --> [1] 0
Type.2 --> [1] 0
Total --> [1] 0
HP --> [1] 0
Attack --> [1] 0
Defense --> [1] 0
Sp..Atk --> [1] 0
Sp..Def --> [1] 0
Speed --> [1] 0
Generation --> [1] 0
Legendary --> [1] 0

From the above observation, it seems that there are no missing values. But there are more empty values(i.e missing values) in the data-set

Converting the empty values in missing values

df[df == ""] <- NA
for ( col in 1:ncol(df)) { 
  cat(colnames(df)[col])
  cat(" --> ")
  print(sum(is.na(df[,col])))
}
Name --> [1] 0
Type.1 --> [1] 0
Type.2 --> [1] 386
Total --> [1] 0
HP --> [1] 0
Attack --> [1] 0
Defense --> [1] 0
Sp..Atk --> [1] 0
Sp..Def --> [1] 0
Speed --> [1] 0
Generation --> [1] 0
Legendary --> [1] 0
print("Percentage of Missing values in Type.2 attribute")
[1] "Percentage of Missing values in Type.2 attribute"
print((abs(nrow(df) - sum(is.na(df['Type.2'])))) / nrow(df))
[1] 0.5175

There are 51% missing values in ‘Type-2’ attribute

1)Bar Chart

ggplot(df, 
       aes(x = Type.1, fill = Legendary)) + 
       geom_bar(position = "stack", color='black') + 
       labs(x = "Type-1", y = "Count", title  = "Contribution of Type-1 and Legendary") + 
       coord_flip() 

Number of Pokemon by Type-1

df %>%
  group_by(Type.1) %>% summarise(number = n()) %>%
  ggplot(aes(x = reorder(Type.1, number), y = number , fill = Type.1)) +
  geom_bar(stat = 'identity', color='black') +
  labs(x = "Type-1 of Pokemon", y = "Number of Pokemon", title  = "Number of Pokemon by Type-1") + 
  coord_flip() + geom_text(aes(label = number), hjust = -1.0)

Number of Pokemon by Type-2

df %>%filter(Type.2 != '') %>% group_by(Type.2) %>% summarise(number = n()) %>%
  ggplot(aes(x = reorder(Type.2, number), y = number , fill = Type.2)) +
  geom_bar(stat = 'identity', color='black') +
  labs(x = "Type-2 of Pokemon", y = "Number of Pokemon", title  = "Number of Pokemon by Type-2") + 
  coord_flip() + geom_text(aes(label = number), hjust = -1.0)

2)Scatter plot

Pokemons with higher attack ratings are faster.

ggplot(df, aes(Attack, Defense)) + geom_jitter(aes(col=Speed)) + 
        scale_color_gradient(low="blue", high="darkorange") + 
        ggtitle("Defense vs Attack wrt Speed")

Correlation Matrix

ggpairs(df, columns = c('Attack', 'Defense', 'HP', 'Sp..Atk', 'Sp..Def', 'Speed')) +
         theme_bw() +labs(title = 'Correlation Matrix of Pokemon Stats')

 plot: [1,1] [==>-------------------------------------------------------------------------------------------]  3% est: 0s 
 plot: [1,2] [====>-----------------------------------------------------------------------------------------]  6% est: 0s 
 plot: [1,3] [=======>--------------------------------------------------------------------------------------]  8% est: 1s 
 plot: [1,4] [=========>------------------------------------------------------------------------------------] 11% est: 1s 
 plot: [1,5] [============>---------------------------------------------------------------------------------] 14% est: 1s 
 plot: [1,6] [===============>------------------------------------------------------------------------------] 17% est: 1s 
 plot: [2,1] [=================>----------------------------------------------------------------------------] 19% est: 1s 
 plot: [2,2] [====================>-------------------------------------------------------------------------] 22% est: 1s 
 plot: [2,3] [=======================>----------------------------------------------------------------------] 25% est: 1s 
 plot: [2,4] [=========================>--------------------------------------------------------------------] 28% est: 1s 
 plot: [2,5] [============================>-----------------------------------------------------------------] 31% est: 0s 
 plot: [2,6] [==============================>---------------------------------------------------------------] 33% est: 0s 
 plot: [3,1] [=================================>------------------------------------------------------------] 36% est: 0s 
 plot: [3,2] [====================================>---------------------------------------------------------] 39% est: 0s 
 plot: [3,3] [======================================>-------------------------------------------------------] 42% est: 0s 
 plot: [3,4] [=========================================>----------------------------------------------------] 44% est: 0s 
 plot: [3,5] [===========================================>--------------------------------------------------] 47% est: 0s 
 plot: [3,6] [==============================================>-----------------------------------------------] 50% est: 0s 
 plot: [4,1] [=================================================>--------------------------------------------] 53% est: 0s 
 plot: [4,2] [===================================================>------------------------------------------] 56% est: 0s 
 plot: [4,3] [======================================================>---------------------------------------] 58% est: 0s 
 plot: [4,4] [========================================================>-------------------------------------] 61% est: 0s 
 plot: [4,5] [===========================================================>----------------------------------] 64% est: 0s 
 plot: [4,6] [==============================================================>-------------------------------] 67% est: 0s 
 plot: [5,1] [================================================================>-----------------------------] 69% est: 0s 
 plot: [5,2] [===================================================================>--------------------------] 72% est: 0s 
 plot: [5,3] [=====================================================================>------------------------] 75% est: 0s 
 plot: [5,4] [========================================================================>---------------------] 78% est: 0s 
 plot: [5,5] [===========================================================================>------------------] 81% est: 0s 
 plot: [5,6] [=============================================================================>----------------] 83% est: 0s 
 plot: [6,1] [================================================================================>-------------] 86% est: 0s 
 plot: [6,2] [===================================================================================>----------] 89% est: 0s 
 plot: [6,3] [=====================================================================================>--------] 92% est: 0s 
 plot: [6,4] [========================================================================================>-----] 94% est: 0s 
 plot: [6,5] [==========================================================================================>---] 97% est: 0s 
 plot: [6,6] [==============================================================================================]100% est: 0s 
                                                                                                                          

3)Density Plot(Univariate analysis)

density_hp =  ggplot(data=df, aes(HP)) + 
              geom_density(col="white",fill="pink", alpha=0.8) + 
              ggtitle("Density Plot of HP")

density_speed = ggplot(data=df, aes(Speed)) + 
                geom_density(col="white", fill="darkorchid", alpha=0.8) + 
                ggtitle("Density Plot of Speed Characterstics")

density_attack = ggplot(data=df, aes(Attack)) + 
                 geom_density(col="white", fill="orange", alpha=0.7) + 
                 ggtitle("Density Plot of Attack Characterstics")

density_defense = ggplot(data=df, aes(Defense)) + 
                  geom_density(col="white", fill="firebrick", alpha=0.7) + 
                  ggtitle("Density Plot of Defense Characterstics")

grid.arrange(density_hp, density_speed, density_attack, density_defense, ncol=2)

4)Box-Plot(Multi-variate Analysis)

Score of Pokemon by generation

## HP(Highest Power) --> Key
## Speed --> Value

df %>% gather(key, value, HP:Speed) %>% ggplot(aes(x = Generation, y = value, fill = as.factor(Generation))) +
       geom_boxplot() + facet_grid(~key) + labs(x="Generation", y="Score", title="Various score based on Generation flag") 

Score of Pokemon by Legendary type

## HP(Highest Power) --> Key
## Speed --> Value
df %>% gather(key, value, HP:Speed) %>% ggplot(aes(x=Legendary, y=value, fill=as.factor(Legendary))) +
       geom_boxplot() + facet_grid(~key) + labs(x="Lengendry", y="Score", title="Various score based on Lengendry flag")

5) Pie-Chart(Multi-Variate Analysis)

df1 = data.frame(unique(df$Type.1),aggregate(df,by=list(df$Type.1),FUN=median)["HP"])
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
  argument is not numeric or logical: returning NA
plot_ly(df1,labels=~unique.df.Type.1.,values =~HP,type ="pie")
LS0tCnRpdGxlOiAiQml2YXJpYXRlIEFuYWx5c2lzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICBkZl9wcmludDogcGFnZWQKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKIyBQcmFzaGFudGguUyAxOU1JRDAwMjAKIyMgQml2YXJpYXRlIEFuYWx5c2lzCgojIyBJbXBvcnRpbmcgdGhlIGxpYnJhcmllcwpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeSh0aWR5cikKbGlicmFyeShyZXNoYXBlMikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeShHR2FsbHkpCmxpYnJhcnkocGxvdGx5KQpgYGAKCiMjIEltcG9ydGluZyB0aGUgZGF0YS1zZXRzCmBgYHtyfQpkZiA9IHJlYWQuY3N2KCdwb2tlbW9uLmNzdicpCmhlYWQoZGYpCmBgYAoKIyMjIFByZVByb2Nlc3NpbmcKCmBgYHtyfQpjYXQoIk51bWJlciBvZiBpbnN0YW5jZXMgIDogIixucm93KGRmKSkKY2F0KCJcbk51bWJlciBvZiBhdHRyaWJ1dGVzIDogIixuY29sKGRmKSkKYGBgCgpgYGB7cn0Kc3RyKGRmMSkKYGBgCgpgYGB7cn0Kc3VtbWFyeShkZjEpCmBgYApgYGB7cn0KZm9yICggY29sIGluIDE6bmNvbChkZikpIHsgCiAgY2F0KGNvbG5hbWVzKGRmKVtjb2xdKQogIGNhdCgiIC0tPiAiKQogIHByaW50KHN1bShpcy5uYShkZlssY29sXSkpKQp9CmBgYAoKRnJvbSB0aGUgYWJvdmUgb2JzZXJ2YXRpb24sIGl0IHNlZW1zIHRoYXQgdGhlcmUgYXJlIG5vIG1pc3NpbmcgdmFsdWVzLgpCdXQgdGhlcmUgYXJlIG1vcmUgZW1wdHkgdmFsdWVzKGkuZSBtaXNzaW5nIHZhbHVlcykgaW4gdGhlIGRhdGEtc2V0CgpDb252ZXJ0aW5nIHRoZSBlbXB0eSB2YWx1ZXMgaW4gbWlzc2luZyB2YWx1ZXMKYGBge3J9CmRmW2RmID09ICIiXSA8LSBOQQpgYGAKCmBgYHtyfQpmb3IgKCBjb2wgaW4gMTpuY29sKGRmKSkgeyAKICBjYXQoY29sbmFtZXMoZGYpW2NvbF0pCiAgY2F0KCIgLS0+ICIpCiAgcHJpbnQoc3VtKGlzLm5hKGRmWyxjb2xdKSkpCn0KYGBgCgpgYGB7cn0KcHJpbnQoIlBlcmNlbnRhZ2Ugb2YgTWlzc2luZyB2YWx1ZXMgaW4gVHlwZS4yIGF0dHJpYnV0ZSIpCnByaW50KChhYnMobnJvdyhkZikgLSBzdW0oaXMubmEoZGZbJ1R5cGUuMiddKSkpKSAvIG5yb3coZGYpKQpgYGAKVGhlcmUgYXJlIDUxJSBtaXNzaW5nIHZhbHVlcyBpbiAnVHlwZS0yJyBhdHRyaWJ1dGUKCiMjIDEpQmFyIENoYXJ0CmBgYHtyfQpnZ3Bsb3QoZGYsIAogICAgICAgYWVzKHggPSBUeXBlLjEsIGZpbGwgPSBMZWdlbmRhcnkpKSArIAogICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAic3RhY2siLCBjb2xvcj0nYmxhY2snKSArIAogICAgICAgbGFicyh4ID0gIlR5cGUtMSIsIHkgPSAiQ291bnQiLCB0aXRsZSAgPSAiQ29udHJpYnV0aW9uIG9mIFR5cGUtMSBhbmQgTGVnZW5kYXJ5IikgKyAKICAgICAgIGNvb3JkX2ZsaXAoKSAKCmBgYAoKTnVtYmVyIG9mIFBva2Vtb24gYnkgVHlwZS0xCmBgYHtyfQpkZiAlPiUKICBncm91cF9ieShUeXBlLjEpICU+JSBzdW1tYXJpc2UobnVtYmVyID0gbigpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKFR5cGUuMSwgbnVtYmVyKSwgeSA9IG51bWJlciAsIGZpbGwgPSBUeXBlLjEpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScsIGNvbG9yPSdibGFjaycpICsKICBsYWJzKHggPSAiVHlwZS0xIG9mIFBva2Vtb24iLCB5ID0gIk51bWJlciBvZiBQb2tlbW9uIiwgdGl0bGUgID0gIk51bWJlciBvZiBQb2tlbW9uIGJ5IFR5cGUtMSIpICsgCiAgY29vcmRfZmxpcCgpICsgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG51bWJlciksIGhqdXN0ID0gLTEuMCkKYGBgCgpOdW1iZXIgb2YgUG9rZW1vbiBieSBUeXBlLTIKYGBge3J9CmRmICU+JWZpbHRlcihUeXBlLjIgIT0gJycpICU+JSBncm91cF9ieShUeXBlLjIpICU+JSBzdW1tYXJpc2UobnVtYmVyID0gbigpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKFR5cGUuMiwgbnVtYmVyKSwgeSA9IG51bWJlciAsIGZpbGwgPSBUeXBlLjIpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScsIGNvbG9yPSdibGFjaycpICsKICBsYWJzKHggPSAiVHlwZS0yIG9mIFBva2Vtb24iLCB5ID0gIk51bWJlciBvZiBQb2tlbW9uIiwgdGl0bGUgID0gIk51bWJlciBvZiBQb2tlbW9uIGJ5IFR5cGUtMiIpICsgCiAgY29vcmRfZmxpcCgpICsgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG51bWJlciksIGhqdXN0ID0gLTEuMCkKYGBgCgojIyAyKVNjYXR0ZXIgcGxvdApQb2tlbW9ucyB3aXRoIGhpZ2hlciBhdHRhY2sgcmF0aW5ncyBhcmUgZmFzdGVyLgpgYGB7cn0KZ2dwbG90KGRmLCBhZXMoQXR0YWNrLCBEZWZlbnNlKSkgKyBnZW9tX2ppdHRlcihhZXMoY29sPVNwZWVkKSkgKyAKICAgICAgICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3c9ImJsdWUiLCBoaWdoPSJkYXJrb3JhbmdlIikgKyAKICAgICAgICBnZ3RpdGxlKCJEZWZlbnNlIHZzIEF0dGFjayB3cnQgU3BlZWQiKQpgYGAKCiMjIyBDb3JyZWxhdGlvbiBNYXRyaXgKYGBge3J9CmdncGFpcnMoZGYsIGNvbHVtbnMgPSBjKCdBdHRhY2snLCAnRGVmZW5zZScsICdIUCcsICdTcC4uQXRrJywgJ1NwLi5EZWYnLCAnU3BlZWQnKSkgKwogICAgICAgICB0aGVtZV9idygpICtsYWJzKHRpdGxlID0gJ0NvcnJlbGF0aW9uIE1hdHJpeCBvZiBQb2tlbW9uIFN0YXRzJykKYGBgCgoKIyMgMylEZW5zaXR5IFBsb3QoVW5pdmFyaWF0ZSBhbmFseXNpcykKYGBge3J9CmRlbnNpdHlfaHAgPSAgZ2dwbG90KGRhdGE9ZGYsIGFlcyhIUCkpICsgCiAgICAgICAgICAgICAgZ2VvbV9kZW5zaXR5KGNvbD0id2hpdGUiLGZpbGw9InBpbmsiLCBhbHBoYT0wLjgpICsgCiAgICAgICAgICAgICAgZ2d0aXRsZSgiRGVuc2l0eSBQbG90IG9mIEhQIikKCmRlbnNpdHlfc3BlZWQgPSBnZ3Bsb3QoZGF0YT1kZiwgYWVzKFNwZWVkKSkgKyAKICAgICAgICAgICAgICAgIGdlb21fZGVuc2l0eShjb2w9IndoaXRlIiwgZmlsbD0iZGFya29yY2hpZCIsIGFscGhhPTAuOCkgKyAKICAgICAgICAgICAgICAgIGdndGl0bGUoIkRlbnNpdHkgUGxvdCBvZiBTcGVlZCBDaGFyYWN0ZXJzdGljcyIpCgpkZW5zaXR5X2F0dGFjayA9IGdncGxvdChkYXRhPWRmLCBhZXMoQXR0YWNrKSkgKyAKICAgICAgICAgICAgICAgICBnZW9tX2RlbnNpdHkoY29sPSJ3aGl0ZSIsIGZpbGw9Im9yYW5nZSIsIGFscGhhPTAuNykgKyAKICAgICAgICAgICAgICAgICBnZ3RpdGxlKCJEZW5zaXR5IFBsb3Qgb2YgQXR0YWNrIENoYXJhY3RlcnN0aWNzIikKCmRlbnNpdHlfZGVmZW5zZSA9IGdncGxvdChkYXRhPWRmLCBhZXMoRGVmZW5zZSkpICsgCiAgICAgICAgICAgICAgICAgIGdlb21fZGVuc2l0eShjb2w9IndoaXRlIiwgZmlsbD0iZmlyZWJyaWNrIiwgYWxwaGE9MC43KSArIAogICAgICAgICAgICAgICAgICBnZ3RpdGxlKCJEZW5zaXR5IFBsb3Qgb2YgRGVmZW5zZSBDaGFyYWN0ZXJzdGljcyIpCgpncmlkLmFycmFuZ2UoZGVuc2l0eV9ocCwgZGVuc2l0eV9zcGVlZCwgZGVuc2l0eV9hdHRhY2ssIGRlbnNpdHlfZGVmZW5zZSwgbmNvbD0yKQpgYGAKCiMjIDQpQm94LVBsb3QoTXVsdGktdmFyaWF0ZSBBbmFseXNpcykKClNjb3JlIG9mIFBva2Vtb24gYnkgZ2VuZXJhdGlvbgpgYGB7cn0KIyMgSFAoSGlnaGVzdCBQb3dlcikgLS0+IEtleQojIyBTcGVlZCAtLT4gVmFsdWUKCmRmICU+JSBnYXRoZXIoa2V5LCB2YWx1ZSwgSFA6U3BlZWQpICU+JSBnZ3Bsb3QoYWVzKHggPSBHZW5lcmF0aW9uLCB5ID0gdmFsdWUsIGZpbGwgPSBhcy5mYWN0b3IoR2VuZXJhdGlvbikpKSArCiAgICAgICBnZW9tX2JveHBsb3QoKSArIGZhY2V0X2dyaWQofmtleSkgKyBsYWJzKHg9IkdlbmVyYXRpb24iLCB5PSJTY29yZSIsIHRpdGxlPSJWYXJpb3VzIHNjb3JlIGJhc2VkIG9uIEdlbmVyYXRpb24gZmxhZyIpIApgYGAKClNjb3JlIG9mIFBva2Vtb24gYnkgTGVnZW5kYXJ5IHR5cGUKYGBge3J9CiMjIEhQKEhpZ2hlc3QgUG93ZXIpIC0tPiBLZXkKIyMgU3BlZWQgLS0+IFZhbHVlCmRmICU+JSBnYXRoZXIoa2V5LCB2YWx1ZSwgSFA6U3BlZWQpICU+JSBnZ3Bsb3QoYWVzKHg9TGVnZW5kYXJ5LCB5PXZhbHVlLCBmaWxsPWFzLmZhY3RvcihMZWdlbmRhcnkpKSkgKwogICAgICAgZ2VvbV9ib3hwbG90KCkgKyBmYWNldF9ncmlkKH5rZXkpICsgbGFicyh4PSJMZW5nZW5kcnkiLCB5PSJTY29yZSIsIHRpdGxlPSJWYXJpb3VzIHNjb3JlIGJhc2VkIG9uIExlbmdlbmRyeSBmbGFnIikKYGBgCgojIyA1KSBQaWUtQ2hhcnQoTXVsdGktVmFyaWF0ZSBBbmFseXNpcykKYGBge3J9CmRmMSA9IGRhdGEuZnJhbWUodW5pcXVlKGRmJFR5cGUuMSksYWdncmVnYXRlKGRmLGJ5PWxpc3QoZGYkVHlwZS4xKSxGVU49bWVkaWFuKVsiSFAiXSkKcGxvdF9seShkZjEsbGFiZWxzPX51bmlxdWUuZGYuVHlwZS4xLix2YWx1ZXMgPX5IUCx0eXBlID0icGllIikKYGBgCgoK